<?php
/**
 * Phrappe_Bootstrap
 *
 * Phrappe_Bootstrap is used to automate the process of setting up routing
 * and controller directory information before dispatching the ZF front
 * controller.
 *
 * Phrappe_Bootstrap implements the Singleton pattern, so only one instance
 * will ever exist.
 *
 * @copyright   Copyright (c) 2006, John D Wells Jr
 * @author      John D Wells Jr <mailto:wellsdjohn@gmail.com>
 * @category    Phrappe
 * @package     Phrappe_Bootstrap
 * @uses        Zend_Controller_Front
 * @uses        Phrappe_ConfigLoader_RewriteRouter
 */

/** Zend_Controller_Front */
require_once 'Zend/Controller/Front.php';

/** Zend_ConfigLoader_RewriteRouter */
require_once 'Phrappe/ConfigLoader/RewriteRouter.php';

/**
 * @copyright   Copyright (c) 2006 John D Wells Jr
 * @author      John D Wells Jr <mailto:wellsdjohn@gmail.com>
 * @category    Phrappe
 * @package     Phrappe_Bootstrap
 * @uses        Zend_Controller_Front
 * @uses        Phrappe_ConfigLoader_RewriteRouter
 */
class Phrappe_Bootstrap
{
    /**
     * Instance of Phrappe_Bootstrap
     * @var Phrappe_Bootstrap
     */
    static private $_instance = null;

    /**
     * Instance of Zend_Controller_Front
     * @var Zend_Controller_Front
     */
    protected $_controller = null;

    /**
     * Instance of Phrappe_ConfigLoader_RewriteRouter
     * @var Phrappe_ConfigLoader_RewriteRouter
     */
    protected $_loaderRewriteRouter = null;

    /**
     * Instance of Zend_Config
     * @var Zend_Config
     */
    protected $_zendConfig = null;
    
    /**
     * Singleton pattern
     *
     * Instantiate properties
     */
    private function __construct()
    {
        $this->_controller = Zend_Controller_Front::getInstance();
        $this->_loaderRewriteRouter = new Phrappe_ConfigLoader_RewriteRouter();
    }

    /**
     * Singleton pattern
     */
    private function __clone()
    {}

    /**
     * Return one and only one instance of the Phrappe_Bootstrap object
     *
     * @return Phrappe_Bootstrap
     */
    static public function getInstance()
    {
        if (!self::$_instance instanceof self) {
           self::$_instance = new self();
        }

        return self::$_instance;
    }

    /**
     * Convenience feature, calls getInstance()
     *                                      ->setRouter()
     *                                      ->setControllerDirectory()
     *                                      ->dispatch()
     *
     * @param Zend_Config $zendConfig
     */
    static public function run(Zend_Config $zendConfig)
    {
        self::getInstance()
            ->setRouter($zendConfig->router)
            ->setControllerDirectory($zendConfig->directory)
            ->dispatch();
    }

    /**
     * Sets the router object, based on a provided Zend_Config object
     * that is filled with router information.
     *
     * @param Zend_Config $cfgRouter
     */
    public function setRouter(Zend_Config $cfgRouter)
    {
        $this->_controller
             ->setRouter($this->_loaderRewriteRouter->run($cfgRouter));
        
        // Return self to allow for 'waterfall' calls
        return $this;
    }
    
    /**
     * Sets the controller directory, based on a provided Zend_Config object
     * that is filled with directory structure information.
     *
     * @param Zend_Config $cfgDirectory
     */
    public function setControllerDirectory(Zend_Config $cfgDirectory)
    {
        $this->_controller
             ->setControllerDirectory($cfgDirectory->controllers);
        
        // Return self to allow for 'waterfall' calls
        return $this;
    }
    
    /**
     * Dispatch an HTTP request to a controller/action.
     *
     * Could caching be done at this point?  Do we know the request route?
     * Perhaps caching hooks could be placed in multiple locations?
     */
    public function dispatch()
    {
        try {
            $this->_controller->dispatch();
        } catch (Zend_Controller_Action_Exception $e) {
            die('404');
        }
    }
}